import LXCOM from '../common/common.js'
import baseunitgrah from './baseunitgrah.js'
import { CoordTRFUtil } from '../common/tools/coordtool.js'
import Coord from '../common/struct/coord.js'
import bezierCurveAction from './action/bezierCurveAction.js'
import utilFuncs from '../common/tools/utilfuncs.js'
var funcs = utilFuncs.UtilFuncs;
import GlobalConst from '../common/globalConst.js'
var global = GlobalConst.GlobalConst;
import {FillUtil} from '../graph/paintutil/fillutil.js'
import {Strokeutil} from '../graph/paintutil/strokeutil.js'

import {LGXEnums}  from '../common/sysenum.js'

import polygon from '../common/struct/basestruct/polygon.js'
import graphmodsvc from './graphmodsvc.js'

class BezierCurveGraph extends baseunitgrah.BaseUnitGraph {
    constructor(type) {
        super(type);
        var p = new Coord.MultiPos();
        this.setPos(p);

        var action = new bezierCurveAction.BezierCurveAction(this);
        this.setActionSvc(action);
        this.m_graphType = LGXEnums.LGXGraphType.BezierCurve_type;
    }

    display(map, mapInfo,forClip) {
        var scaling = mapInfo.getScaling();
        let posList = [];
        var position = this.getPos();
        var ptCount = position.posList.length;
        var pt = position.posList[0];
        var p0 = CoordTRFUtil.world2Screen(pt, mapInfo);
        posList.push(p0);
        for (var i = 1; i < ptCount; i++) {
            pt = position.posList[i];
            var p = CoordTRFUtil.world2Screen(pt, mapInfo);
            posList.push(p);
        }
        posList.push(p0);
        if (this._finishFlag) {
            this.disBezierCurve(map, posList);
            Strokeutil.active(this._lineDef, this, map, mapInfo);
            if (!forClip)
            FillUtil.active(this._fillDef, map, this, mapInfo,false);
        }
        else {
            this.disOutLine(map, posList);
            if (ptCount == 4) {
                this.disBezierCurve(map, posList);
            }
            Strokeutil.active(this._lineDef, this, map, mapInfo);
        }

        super.displayGraphScope(map, mapInfo);
        this.displayFeaturePoint(map, posList, mapInfo);
    }

    disBezierCurve(map, posList) {
        let p0 = posList[0];
        let p1 = posList[1];
        let p2 = posList[2];
        let p3 = posList[3];
        map.beginPath();
        map.moveTo(p0.x, p0.y);
        map.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
        if (this._fillDef.fillStyle != LGXEnums.LGXFillStyle.EMPTY){
             map.closePath();
        }
    }

    disOutLine(map, posList) {
        let p0 = posList[0];
        map.beginPath();
        map.moveTo(p0.x, p0.y);
        for (let i = 1; i < posList.length; i++) {
            let p1 = posList[i];
            map.lineTo(p1.x, p1.y);
        }
        map.closePath();
    }

    disInSymbol(transformInfo,map, mapInfo) {
        var scaling = mapInfo.getScaling();
        let posList = [];
        var position = this.getPos();
        var lenth = position.posList.length;
        for (var i = 0; i < lenth; i++) {
            let pt = position.posList[i];
            let x = pt.x * scaling;
            let y = -pt.y * scaling;
            posList.push({x, y});
        }
        this.disBezierCurve(map, posList);

        Strokeutil.active(this._lineDef, this, map, mapInfo);
        FillUtil.active(this._fillDef, map,this,mapInfo,true);
    }

    calScope(mapscale) {
        var position = this.getPos();
        var lenth = position.posList.length;
        if (lenth < 2) {
            return;
        }
        let rect = position.getZone();
        this._zone.clone(rect);
    }

    getLocalZone() {
        let mtx = this.getLocalMatrix();
        let inverseMtx = mtx.Inverse();
        let rect = new LXCOM.LGXRect(0, 0, 0, 0);
        let position = this.getPos();
        let length = position.posList.length;
        for (var i = 0; i < length; i++) {
            let pt = position.posList[i];
            let localPt = inverseMtx.MultT({ x: pt.x, y: pt.y, z: 0 });//求相对于控制图形局部坐标系的局部坐标  
            let x = localPt.x;
            let y = localPt.y;

            if (i == 0) {
                rect.left = x;
                rect.right = x;
                rect.top = y;
                rect.bottom = y;
            }
            rect.left = Math.min(rect.left, x);
            rect.right = Math.max(rect.right, x);
            rect.bottom = Math.min(rect.bottom, y);
            rect.top = Math.max(rect.top, y);
        }
        return rect;
    }

    distance(tPos, scaling, mapscale) {
        var position = this.getPos();
        var lenth = position.posList.length;
        if (lenth < 2) {
            return -1;
        }
        if (!super.preCheckInScope(tPos, scaling)) {
            return -1;
        }
        var cmpGap = super.getSelCmpGap(scaling, mapscale);
        var dis = 0;
        var pCntPos = null;
        var pPrePos = position.posList[0];
        for (var i = 0; i < lenth - 1; i++) {
            pCntPos = position.posList[i + 1];
            var lLen = funcs.distanceLineSec4Visual(tPos, pPrePos, pCntPos, scaling);
            if ((lLen < dis) || (dis < 0)) {
                dis = lLen;
            }
            if (dis <= cmpGap) {
                return 0;
            }
            pPrePos = pCntPos;
        }
        return dis;
    }

    displayFeaturePoint(map, posList, mapInfo) {
        if (this._selected) {
            super.displayFeaturePoint(map, mapInfo);
            this.displayControlPoint(map, posList) ;
        }
        else if (this.m_pContainer && this.m_pContainer._selected){
            this.displayControlPoint(map, posList) ;
        }
    }

    displayControlPoint(map, posList) {
        let p0 = posList[0];//开始点
        super.drawFocusPoint(map, p0.x, p0.y, "#ff00ff");
        let p1 = posList[1];//控制点1
        super.drawFocusPoint(map, p1.x, p1.y, "#ff00ff");
        let p2 = posList[2];//控制点2
        super.drawFocusPoint(map, p2.x, p2.y, "#ff00ff");
        let p3 = posList[3];//终止点
        super.drawFocusPoint(map, p3.x, p3.y, "#ff00ff");
    }

    calculateSubKind(tPoint, scaling, mapscale) {
        var position = this.getPos();
        var lenth = position.posList.length;
        if (lenth < 2) {
            return 0;
        }
        var seleKind = 0;
        var tAbsorbPt = new LXCOM.LGXPoint();
        tAbsorbPt.clone(tPoint);

        var cmpGap = super.getSelCmpGap(scaling, mapscale);

        var lDis = -1;
        var nMinDis = 99;
        var pCntPos = null;
        var pPrePos = position.posList[0];
        for (var i = 1; i < lenth; i++) {
            pCntPos = position.posList[i];
            lDis = funcs.distanceLineSec4Visual(tPoint, pPrePos, pCntPos, scaling);
            if (lDis <= cmpGap && lDis >= 0 && lDis <= nMinDis) {
                nMinDis = lDis;
                tAbsorbPt.clone(tPoint);
                var nConnType = funcs.adsorbPosOnLineSec(tAbsorbPt, pPrePos, pCntPos, scaling);
                if (nConnType % 10 == 0) {
                    seleKind = lenth + 1;
                }
                else {
                    var n = Math.floor(nConnType / 10);
                    seleKind = n + i;
                }
            }
            pPrePos = pCntPos;
        }

        if (seleKind > 0) {
            tPoint.clone(tAbsorbPt);
        }

        return seleKind;
    }

    calculateSubControlPoint(tPoint, scaling, mapscale) {
        var position = this.getPos();
        var lenth = position.posList.length;
        if (lenth < 2) {
            return 0;
        }
        var seleKind = 0;
        var tAbsorbPt = new LXCOM.LGXPoint();
        tAbsorbPt.clone(tPoint);

        let cmpGap = global.FocusSelGap;
        var nMinDis = 99;
        for (var i = 0; i < lenth; i++) {
            let pCntPos = position.posList[i];
            let lDis = funcs.distancePoint(tPoint, pCntPos, scaling);
            if (lDis <= cmpGap && lDis >= 0 && lDis <= nMinDis) {
                nMinDis = lDis;
                tAbsorbPt.clone(tPoint);
                seleKind = i+1;
            }
        }

        if (seleKind > 0) {
            tPoint.clone(tAbsorbPt);
        }
        return seleKind;
    }

    movePosOffset(tOffset, modCmdInfo) {
        if (this._selKind < 1) {
            return;
        }

        var position = this.getPos();
        var lenth = position.posList.length;
        if (this._selKind > lenth) {
            this.translate(tOffset, modCmdInfo.mapscale,false);
        }
        else if (this._selKind <= lenth && this._selKind > 0) {
            let pt = position.posList[this._selKind - 1];
            pt.x += tOffset.x;
            pt.y += tOffset.y;
        }
    }

    getMainFeaturePTLst(tFeaturePTLst) {
        var position = this.getPos();
        var lenth = position.posList.length;
        for (var i = 0; i < lenth; i++) {
            var pt = position.posList[i];
            var featurePT = new LXCOM.LGXPoint();
            featurePT.clone(pt);
            tFeaturePTLst.push({pt:featurePT,kind:LGXEnums.AuxPointKind.end});
        }
    }

    assignInfo(info) {
        super.assignInfo(info);
    }

    modifyAttribute(info, mapscale) {
        super.modifyAttribute(info,mapscale);
        this.calScope(mapscale);
    }

    toInfo() {
        var info = new polygon.Polygon();
        this.toInfo4InheritClass(info);
        info.strPosition = this.getPos().toString();
        return info;
    }


    modifyCoord(propName, propVal, mapscale) {
        var position = this.getPos();
        if (propName == "poslist") {
            var lenth = position.posList.length;
            for (var i = 0; i < lenth; i++) {
                var pt = position.posList[i];
                let jsonObj = propVal[i];
                pt.x = parseFloat(jsonObj.x);
                pt.y = parseFloat(jsonObj.y);
            }
        }
        this.notifyToObserver();
        this.calScope(mapscale);
    }

    getCoordInfo() {
        let graphPropDef = this.getCoordPropDef();
        let tableData = [];
        let arr = [];
        var position = this.getPos();
        var lenth = position.posList.length;
        for (var i = 0; i < lenth; i++) {
            var pt = position.posList[i];
            arr.push({ x: pt.x, y: pt.y });
        }

        let polistObj = {
            propName: 'poslist',
            propLabel: '顶点列表',
            propValue: arr
        };
        tableData.push(polistObj);

        let tableForm = {
            'tableData': tableData
        };
        return { graphPropDef, tableForm };
    }

    getCoordPropDef() {
        let graphPropDef = {
            poslist: {
                vtype: global.PtList_CoordType,
                range: { min: 1, max: 10 },
            }
        }
        return graphPropDef;
    }

    getPosCopy() {
        let pos = new Coord.MultiPos();
        pos.clone(this._position);
        return pos;
    }
}


export default { BezierCurveGraph }
